/*
	nml_cat
	Nikolaus Loening, November 10, 2000

	Last Modified:	may 21, 2003

This program seperates a ser file into a series of ser files.
This is not a very general program.

*/

//	Declare some constants and variables

//#define BUFFER		131072	// size of buffer
//#define OUTPUT		8		// number of output files

int	iTD,iTD1,bytorda,
	*buff,*buff1,*buff2,*buff3,*buff4,*buff5,*buff6,*buff7,*buff8,
 	i,j,size;
			
char	outname1[PATH_LENGTH],
	outname2[PATH_LENGTH],
	outname3[PATH_LENGTH],
	outname4[PATH_LENGTH],
	outname5[PATH_LENGTH],
	outname6[PATH_LENGTH],
	outname7[PATH_LENGTH],
	outname8[PATH_LENGTH],
	inname[PATH_LENGTH];		// input file pathname

void ENDIAN_CONVERT(char *data, int n, int numberofbytes,int bytorda);
void NML_ERROR(char error_text[]);
int **NML_IMATRIX(int n1, int n2);
int ***NML_ITENSOR(int n1, int n2,int n3);
int *NML_IVECTOR(int n);
char *NML_CVECTOR(int n);

FILE 	*out1, 
 	*out2,
	*out3,
	*out4,
	*out5,
	*out6,
	*out7,
	*out8,
	*in1;

GETCURDATA;
FETCHPARS("TD",&iTD);
FETCHPAR1S("TD",&iTD1);
FETCHPARS("BYTORDA",&bytorda);	/* 1 for big endian, 0 for little endian	*/
strcpy(text,"ser");

(void)sprintf( inname,"%s/data/%s/nmr/%s/%d/%s",disk,user,name,expno,text);
in1 = fopen( inname,"rb" );


buff=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff) STOPMSG("Could not allocate enough memory (buff)");

buff1=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff1) STOPMSG("Could not allocate enough memory (buff1)");

buff2=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff2) STOPMSG("Could not allocate enough memory (buff2)");

buff3=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff3) STOPMSG("Could not allocate enough memory (buff3)");

buff4=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff4) STOPMSG("Could not allocate enough memory (buff4)");

buff5=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff5) STOPMSG("Could not allocate enough memory (buff5)");

buff6=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff6) STOPMSG("Could not allocate enough memory (buff6)");

buff7=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff7) STOPMSG("Could not allocate enough memory (buff7)");

buff8=(int *) malloc((size_t)(2*iTD*sizeof(int)));
if (!buff8) STOPMSG("Could not allocate enough memory (buff8)");


(void)sprintf( outname1,"%s/data/%s/nmr/%s/%d/%s",disk,user,name,expno+1,text);
	out1 = fopen( outname1,"wb" );

(void)sprintf( outname2,"%s/data/%s/nmr/%s/%d/%s",disk,user,name,expno+2,text);
	out2 = fopen( outname2,"wb" );

(void)sprintf( outname3,"%s/data/%s/nmr/%s/%d/%s",disk,user,name,expno+3,text);
	out3 = fopen( outname3,"wb" );


        for (j=0; j < iTD1; j++)
	{
	

		fread(buff1,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff1,iTD*2,sizeof(int),bytorda);
		fread(buff2,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff2,iTD*2,sizeof(int),bytorda);
		fread(buff3,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff3,iTD*2,sizeof(int),bytorda);
		fread(buff4,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff4,iTD*2,sizeof(int),bytorda);
		fread(buff5,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff5,iTD*2,sizeof(int),bytorda);
		fread(buff6,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff6,iTD*2,sizeof(int),bytorda);
		fread(buff7,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff7,iTD*2,sizeof(int),bytorda);
		fread(buff8,sizeof(int),iTD*2,in1);
ENDIAN_CONVERT(buff8,iTD*2,sizeof(int),bytorda);
		
		for (i=0;i <= iTD*2-1; i=i+1)
		{
		

		buff[i]=buff1[i]+buff2[i]+buff3[i]+buff4[i]+buff5[i]+buff6[i]+buff7[i]+buff8[i];
		
		}
		

		fwrite(buff,sizeof(int),iTD*2,out1);


		for (i=0;i <= iTD*2-1; i++)
		{
		buff[i]=buff1[i]+buff2[i]-buff3[i]-buff4[i]+buff5[i]+buff6[i]-buff7[i]-buff8[i];
		}
		fwrite(buff,sizeof(int),iTD*2,out2);
		
		for (i=0;i <= iTD*2-1; i++)
		{
		buff[i]=buff1[i]-buff2[i]-buff3[i]-buff4[i]-buff5[i]+buff6[i]+buff7[i]+buff8[i];
		}
		fwrite(buff,sizeof(int),iTD*2,out3);
		
Proc_err(INFO_OPT,"Pssing Row %d of %d.",j,iTD1);

	}
	free(buff1);
	free(buff);
	free(buff2);
	free(buff3);
	free(buff4);
	free(buff5);
	free(buff6);
	free(buff7);
	free(buff8);

	fclose(out1);
	fclose(out2);
	fclose(out3);

	fclose(in1);

DATASET(name, expno+1, 1, disk, user);
STOREPARS("BYTORDA",0);
XFB;
DATASET(name, expno+1, 1, disk, user);
STOREPARS("BYTORDA",0);
XFB;
DATASET(name, expno+1, 1, disk, user);
STOREPARS("BYTORDA",0);
XFB;

QUIT


int LITTLE_ENDIAN()
// Returns 1 if little endian, 0 if big endian
{
  short a = 0x0001;
  return (int)*((unsigned char*) (&a));
}



void ENDIAN_CONVERT(char *data, int n, int numberofbytes, int big_endian)
/*  This function reverses the byte order of the given data,
the input data can be any data type as long as it is made up
of a whole number of bytes.

	data		is the data you want converted
	n 		is the number of points in the array
	numberofbytes	should be equal to "sizeof(type)" for input data
	big_endian	1 for big endian, 0 for little endian			*/
{ 
	int	i,j;
	char	*temp;

				// Reorder bytes if endianess doesn't match
	if (big_endian == LITTLE_ENDIAN())
	{
		temp=NML_CVECTOR(numberofbytes);
		for (i=0; i<n; i++)
		{
			for (j=0;j<numberofbytes;j++) temp[j] = *data++;
			data = data-numberofbytes;
			for (j=(numberofbytes-1);j>=0;j--) *data++ = temp[j];
		}
		free(temp);

	}
}



void NML_ERROR(char error_text[])
/* Standard error handler	

	ERR_ERR	       -1	error processing error
	ERR_OK		0	ok, execution can continue
	ERR_CANCEL	1	cancel erroneous operation
	ERR_IGNORE	2	ignore erroneous operation
	ERR_RETRY	3	retry erroneous operation
	ERR_ABT		4	abort erroneous operation
*/
{
	Proc_err(ERR_OK,"%s",error_text);
}

int **NML_IMATRIX(int n1, int n2)
     /*  Allocate an int matrix with subscript range m[0..n1-1][0..n2-1]  */
{
  int **m,i;

  /*  allocate pointers to rows  */
  m=(int **)malloc((size_t)(n1*sizeof(int*)));
  if (!m)
	{
	NML_ERROR("allocation failure 1 in NML_IMATRIX()");
	return m;
	}

  /*  allocate rows and set pointers to them  */
  m[0]=(int *)malloc((size_t)(n1*n2*sizeof(int)));
  if (!m[0])
	{
	NML_ERROR("allocation failure 2 in NML_IMATRIX()");
	return m[0];
	}

  for (i=1;i<=n1-1;i++) m[i]=m[i-1]+n2;

  /*  return pointer to array of pointers to rows  */
  return m;
}

int ***NML_ITENSOR(int n1, int n2, int n3)
	/* Allocate an int tensor with subscipt range t[0..n1-1][0..n2-1][0..n3-1]  */
{
  int ***t, i, j;

  t = (int ***) malloc((size_t)(n1*sizeof(int**)));
  if (!t)
	{
	NML_ERROR("allocation failure 1 in NML_ITENSOR()");
	return t;
	}

  /*  allocate arrays and set pointers to them  */
  t[0]=(int **)malloc((size_t)(n1*n2*sizeof(int*)));
  if (!t[0])
	{
	NML_ERROR("allocation failure 2 in NML_ITENSOR()");
	return t[0];
	}

  /*  allocate rows and set pointers to them  */
  t[0][0]=(int *)malloc((size_t)(n1*n2*n3*sizeof(int)));
  if (!t[0][0])
	{
	NML_ERROR("allocation failure 3 in NML_ITENSOR()");
	return t[0][0];
	}
  for (j=1;j<n2;j++) t[0][j]=t[0][j-1]+n3;
  for (i=1;i<n1;i++)
	{
	t[i]=t[i-1]+n2;
	t[i][0]=t[i-1][0]+n2*n3;
	for(j=1;j<n2;j++)
		{
		t[i][j]=t[i][j-1]+n3;
		}
	}

  /*  return pointer to tensor of pointers to arrays of pointers to rows  */
  return t;
}

int *NML_IVECTOR(int n)
     /*  Allocate an int vector with subscript range v[0..n] 	*/
{
	int *v;
	v=malloc(n*sizeof(int));
	if (!v)
		{
		NML_ERROR("allocation failure in NML_IVECTOR()");
		return v;
		}
	return v;
}


char *NML_CVECTOR(int n)
/*  Allocate a char vector with subscript range v[0..n] 	*/
{
	char *v;
	v=malloc(n*sizeof(char));
	if (!v)
		{
		NML_ERROR("allocation failure in NML_CVECTOR()");
		return v;
		}
	return v;
}













